package org.sage.sdk.dada.infrastructure.utils;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import org.sage.sdk.dada.infrastructure.common.BaseEntity;
import org.sage.sdk.dada.infrastructure.common.annotation.Aggregate;
import org.sage.sdk.dada.infrastructure.common.attributes.BaseAttributes;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * @author 周广明
 * @version v1 2019/12/11 下午5:30
 */
public class GetBodyUtil {

    public static String toJsonStr(BaseEntity entity) {
        return toJSONObject(entity).toJSONString();
    }

    public static JSONObject toJSONObject(BaseEntity entity) {
        Map<String, Field> fieldMap = ReflectUtil.getFieldMap(entity.getClass());

        return getFieldValue(fieldMap, entity);
    }


    private static JSONObject getFieldValue(Map<String, Field> fieldMap, Object entity) {
        JSONObject jsonObject = new JSONObject();

        for (String fileName : fieldMap.keySet()) {

            String key = StrUtil.toUnderlineCase(fileName);
            Object value = ReflectUtil.getFieldValue(entity, fieldMap.get(fileName));

            // is null
            if (value == null) {
                continue;
            }

            // get aggregate Annotation
            Aggregate annotation = value.getClass().getAnnotation(Aggregate.class);

            // if 'annotation == null', is attributes.
            if (annotation == null) {
                // is attributes
                BaseAttributes attributes = (BaseAttributes) value;
                jsonObject.put(key, attributes.getVal());

            } else {
                // is aggregate

                // name
                String simpleName = value.getClass().getSimpleName();
                String fieldName = StrUtil.toUnderlineCase(simpleName);

                // value(is object)

                // get value(is object) attributes
                Map<String, Field> aggregateObjValues = ReflectUtil.getFieldMap(value.getClass());

                // get value(is object) attributes value
                for (String aggregateObjAtt : aggregateObjValues.keySet()) {
                    Field field = aggregateObjValues.get(aggregateObjAtt);
                    BaseAttributes aggregateObj = (BaseAttributes) ReflectUtil.getFieldValue(value, field);

                    // is null
                    if (aggregateObj == null) {
                        continue;
                    }

                    String jsonKey = fieldName + "_" + StrUtil.toUnderlineCase(aggregateObjAtt);
                    jsonObject.put(jsonKey, aggregateObj.getVal());
                }

            }
        }

        return jsonObject;
    }
}